package com.ganzi.ganziitem.netty.conf;

import java.util.List;

import com.ganzi.ganziitem.Utils.CTool;
import com.ganzi.ganziitem.netty.util.CRC16M;
import com.ganzi.ganziitem.netty.util.FormatTransfer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MessageDecoder extends ByteToMessageDecoder {
	private static Logger log = LoggerFactory.getLogger(MessageDecoder.class);
	private final int WRITE_SIZE = 8;

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in,
			List<Object> out) {
		try {
			in.discardReadBytes();
			in.markReaderIndex();
			int index = in.readerIndex();

			// 如果没有接收完Header部分（4字节），直接返回false
			if (in.readableBytes() < 4) {
				// logger.error( "|"
				// + ctx.channel().remoteAddress() +
				// "|接受到小于四字节的内容:"+in.readableBytes());
				return;
			} else {
				int length = 0;
				byte[] typeBuf = new byte[1];
				in.getBytes(index + 1, typeBuf, 0, 1);
				int type = (int) typeBuf[0];

				printType(type, ctx);

				// 写地址列表与写账户标志等
				if (type == 6 || type == 16) {

					if (in.readableBytes() < WRITE_SIZE) {
						in.resetReaderIndex();
						return;
					}
					byte[] decoded = new byte[WRITE_SIZE];
					in.readBytes(decoded);
					out.add(decoded);

				} else if (type == 3 || type == 51) {

					byte[] bt_length = new byte[2];
					in.getBytes(index + 4, bt_length, 0, 2);
					// 盘管数据长度
					length = FormatTransfer.hBytesToShort(bt_length);
					// 流水号2|modbus默认0000 两个字节|长度2字节|
					// 所以数据包总长度有效盘管数据+8
					length = length + 8;

					// 读到的消息体长度如果小于消息长度，则resetReaderIndex.
					// 这个配合markReaderIndex使用
					// 把readIndex重置到mark的地方
					if (in.readableBytes() < length) {
						in.resetReaderIndex();
						return;
					}
					// 读到的长度，满足消息的长度，开始读取数据
					log.info(CTool.getnowtime() + "|readBytes" + +length);
					byte[] decoded = new byte[length];

					in.readBytes(decoded);
					out.add(decoded);
				} else {
					byte[] decoded = new byte[in.readableBytes()];
					in.readBytes(decoded);
					log.error("|" + ctx.channel().remoteAddress()
							+ "|Accept|" + CRC16M.getBufHexStr(decoded));

					ctx.close();
					log.error("|" + ctx.channel().remoteAddress()
							+ "|illegal message type...  ");
				}

			}

		} catch (Exception e) {
			e.printStackTrace();
			ctx.close();
			log.error("|" + ctx.channel().remoteAddress()
					+ "|decode error  ");
		}

	}

	public void printType(int type, ChannelHandlerContext ctx) {
		if (type == 3) {
			// logger.info(CTool.getnowtime() + "|"
			// + ctx.channel().remoteAddress()
			// + "|get comsu data  msg  back ");

		} else if (type == 51) {
			// logger.info(CTool.getnowtime() + "|"
			// + ctx.channel().remoteAddress()
			// + "|get addrlist msg  back ");
		}

		else if (type == 6) {
			// logger.info(ctx.channel().remoteAddress()
			// + " write msg back");

		} else if (type == 16) {

			// logger.info(CTool.getnowtime() + "|"
			// + ctx.channel().remoteAddress()
			// + "|update dac addrlist msg back ");
		} else {
			log.error(ctx.channel().remoteAddress() + " error type ：" + type);
			ctx.close();

		}

	}

}